<?php
/**
 * Created by PhpStorm.
 * User: figo-009
 * Date: 2017/5/19
 * Time: 15:27
 */
namespace ApigilityGroup\Service;

use Zend\ServiceManager\ServiceManager;
use Zend\Hydrator\ClassMethods as ClassMethodsHydrator;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrineToolPaginator;
use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator as DoctrinePaginatorAdapter;
use Zend\Math\Rand;
use ApigilityGroup\DoctrineEntity;
use ApigilityUser\DoctrineEntity\User;
use ApigilityAddress\DoctrineEntity\Region;

class GroupService
{
    const NO_PARTICIPATION = 0;

    const SEX_MALE = 1;
    const SEX_FEMALE = 2;

    const NEW_GROUP_PARTICIPATION_NUM = 1; //刚刚发起拼团时，人数为1

    const BUY_TYPE_ORIGINAL = 1;
    const BUY_TYPE_GROUP = 2;

    const PARTICIPATION_TYPE_CREATOR = true;
    const PARTICIPATION_TYPE_NO_CREATOE = false;

    protected $classMethodsHydrator;

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    /**
     * @var \ApigilityAddress\Service\Region
     */
    protected $regionService;

    /**
     * @var \ApigilityVIP\Service\Service
     */
    protected $serviceService;

    /**
     * @var \ApigilityGroup\Service\Setting
     */
    protected $settingService;

    protected $serviceManager;

    public function __construct(ServiceManager $services)
    {
        $this->classMethodsHydrator = new ClassMethodsHydrator();
        $this->em = $services->get('Doctrine\ORM\EntityManager');
        $this->serviceService = $services->get('ApigilityVIP\Service\ServiceService');
        $this->regionService = $services->get('ApigilityAddress\Service\RegionService');
        $this->settingService = $services->get('ApigilityGroup\Service\SettingService');
        $this->serviceManager = $services;
    }

    /**
     * 发起拼团
     *
     * @param \stdClass $data
     * @param array $services
     * @return DoctrineEntity\Group
     */
    public function createGroup(\stdClass $data, $user = '', $services = [])
    {
        $group = new DoctrineEntity\Group();
        $user_id = $user->getId();
        if ($user_id != $data->user_id) {
            throw new \Exception('未识别的用户标识', 404);
        }

        $groups = $this->getGroupsByUser($user);
        if(count($groups) >= 1) {
            $participations = $this->serviceManager->get('ApigilityGroup\Service\ParticipationDetailService')->getParticipationDetailsByGroupId($groups[0]->getId(),0);

            if(count($participations) && $participations[0]->getStatus()==0){
                return $groups[0];
            }else{
                throw new \Exception('一个用户只能发起一次拼团', 404);
            }
        }

       /* $participations = $this->serviceManager->get('ApigilityGroup\Service\ParticipationDetailService')->getParticipationDetailsByUser($user);
        if(count($participations)) {
            throw new \Exception('一个用户不能参与多次拼团活动', 404);
        }*/

        $census_register_address = $user->getCensusRegisterAddress();
        if(empty($census_register_address)) {
            throw new \Exception('请先填写户籍地址', 404);
        }

        $group_settings = $this->settingService->getGroupSettingByAddress($census_register_address->getProvince(), $census_register_address->getCity(), $census_register_address->getDistrict());

        $buy_number = $this->generateBuyNumber();

        $group->setUser($user);
        $group->setBuyNumber($buy_number);
        $group->setCreatetime(new \DateTime());
        $group->setGroupSetting($group_settings[0]);
        $group->addService($this->serviceService->getService($data->service_id));
        $group->setGroupname($this->serviceService->getService($data->service_id)->getTitle());

        $this->em->persist($group);
        $this->em->flush();

        $participation_data = new \stdClass();
        $participation_data->buy_number = $buy_number;
        $participation_data->user_id = $user_id;
        $participation = $this->serviceManager
            ->get('ApigilityGroup\Service\ParticipationDetailService')
            ->createParticipationDetail($participation_data, $user, '', $this::PARTICIPATION_TYPE_CREATOR);

        return $group;
    }

    /**
     * 获取用户参团价格
     *
     * @param $user
     * @return boolean|mixed
     * @throws \Exception
     */
    public function getParticipationPrice($user)
    {
        $groups = $this->getGroupsByUser($user);

        $id_card_number = '';
        $personal_certification = $user->getPersonalCertification();
        if(count($personal_certification)){
            $id_card_number = $personal_certification->getIdentityCardNumber();
        }

        $region_code = substr($id_card_number, 0, 6);
        $region_district = $this->regionService->getRegionByCode($region_code, 'district');
        if ($region_district instanceof Region) $region_city = $region_district->getParent();
        if ($region_city instanceof Region) $region_province = $region_city->getParent();


        $group_settings = $this->settingService->getGroupSettingByAddress($region_province, $region_city, $region_district);

        $sex = $user->getSex();
        $male_free = $this->getFreeParticipationBySettingId($group_settings[0]->getId(), $this::SEX_MALE);
        $female_free = $this->getFreeParticipationBySettingId($group_settings[0]->getId(), $this::SEX_FEMALE);

        if($sex == $this::SEX_MALE){
            if($male_free['total'] < $group_settings[0]->getMaleFreeNums()) {
                return 0;
            }
            return $group_settings[0]->getPrice();
        } else {
            if($female_free['total'] < $group_settings[0]->getFemaleFreeNums()) {
                return 0;
            }
            return $group_settings[0]->getPrice();
        }
    }

    /**
     * 生成唯一的团购号
     * @return string
     */
    private function generateBuyNumber()
    {
        $buy_number = null;

        do {
            $time = new \DateTime();
            $string = '123456789abcdefghijklmnopqrstuvwxyz';
            $buy_number = Rand::getString(8, $string);

            $group = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Group')->findBy([
                'buy_number'=>$buy_number
            ]);
        } while (count($group));

        return $buy_number;
    }

    /**
     * 获取某个地区拼团活动下的免费拼团人数
     * @param $setting_id
     * @param $sex
     * @return \ApigilityOrder\DoctrineEntity\Order
     * @throws \Exception
     */
    public function getFreeParticipationBySettingId($setting_id, $sex = '')
    {
        if($sex == $this::SEX_MALE){
            $count = 'sum(COALESCE(g.male_free_participation_nums,0)) as total';
        }else if($sex == $this::SEX_FEMALE){
            $count = 'sum(COALESCE(g.female_free_participation_nums, 0)) as total';
        }else{
            $count = 'sum(COALESCE(g.male_free_participation_nums, 0) + COALESCE(g.female_free_participation_nums, 0)) as total';
        }

        $qb = new QueryBuilder($this->em);
        $qb->select($count)
            ->from('ApigilityGroup\DoctrineEntity\Group', 'g')
            ->groupBy('g.group_setting')
            ->having('g.group_setting = ' . $setting_id);
        $total = $qb->getQuery()->getResult();
        if(count($total)){
            return $total[0];
        } else {
            return $this::NO_PARTICIPATION;
        }
    }

    /**
     * 获取某个地区拼团活动下的总拼团人数
     * @param $setting_id
     * @param $sex
     * @return \ApigilityOrder\DoctrineEntity\Order
     * @throws \Exception
     */
    public function getParticipationBySettingId($setting_id, $sex = '')
    {
        if($sex == $this::SEX_MALE){
            $count = 'sum(COALESCE(g.male_participation_nums,0)) as total';
        }else if($sex == $this::SEX_FEMALE){
            $count = 'sum(COALESCE(g.female_participation_nums, 0)) as total';
        }else{
            $count = 'sum(COALESCE(g.male_participation_nums, 0) + COALESCE(g.female_participation_nums, 0)) as total';
        }

        $qb = new QueryBuilder($this->em);
        $qb->select($count)
            ->from('ApigilityGroup\DoctrineEntity\Group', 'g')
            ->groupBy('g.group_setting')
            ->having('g.group_setting = ' . $setting_id);
        $total = $qb->getQuery()->getResult();
        if(count($total)){
            return $total[0];
        } else {
            return $this::NO_PARTICIPATION;
        }
    }

    /**
     * 获取一个拼团
     *
     * @param $group_id
     * @return \ApigilityGroup\Doctrin
     * +++++++eEntity\Group
     * @throws \Exception
     * @internal param $group_id
     */
    public function getGroup($group_id)
    {
        $group = $this->em->find('ApigilityGroup\DoctrineEntity\Group', $group_id);
        if (empty($group)) throw new \Exception('拼团不存在', 404);
        else return $group;
    }

    /**
     * 获取拼团
     *
     * @param $params
     * @return DoctrinePaginatorAdapter
     */
    public function getGroups($params)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('g')->from('ApigilityGroup\DoctrineEntity\Group', 'g');

        $where = null;
        if (isset($params->user_id)) {
            $qb->innerJoin('g.user', 'gu');
            if (!empty($where)) $where .= ' AND ';
            $where = 'gu.id = :user_id';
        }

        if (isset($params->setting_id)) {
            $qb->innerJoin('g.group_setting', 'gg');
            if (!empty($where)) $where .= ' AND ';
            $where = 'gg.id = :setting_id';
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($params->user_id)) $qb->setParameter('user_id', $params->user_id);
            if (isset($params->setting_id)) $qb->setParameter('setting_id', $params->setting_id);
        }

        $qb->orderBy('g.id', 'desc');

        $doctrine_paginator = new DoctrineToolPaginator($qb->getQuery());
        return new DoctrinePaginatorAdapter($doctrine_paginator);
    }

    /**
     * 获取某个拼团活动所有拼团
     *
     * @param $params
     * @return DoctrinePaginatorAdapter
     */
    public function getGroupsBySettingId($setting_id)
    {
        $qb = new QueryBuilder($this->em);
        $qb->select('g')->from('ApigilityGroup\DoctrineEntity\Group', 'g');

        $where = null;
        if (isset($setting_id)) {
            $where = 'g.group_setting = :setting_id';
        }

        if (!empty($where)) {
            $qb->where($where);
            if (isset($setting_id)) $qb->setParameter('setting_id', $setting_id);
        }

        return $qb->getQuery()->getResult();
    }

    /**
     * 通过团购号获取一个拼团
     *
     * @param $buy_number
     * @return DoctrineEntity\Group
     * @throws \Exception
     */
    public function getGroupByBuyNumber($buy_number)
    {
        $group = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Group')->findBy([
            'buy_number' => $buy_number,
        ]);

        if (count($group)) {
            return $group[0];
        } else {
            //return array("status"=>"405","msg"=>"拼团活动不存在");
            throw new \Exception('拼团活动不存在', 405);
        }
    }

    /**
     * 获取一个拼团
     *
     * @param $user
     * @return DoctrineEntity\Group
     * @throws \Exception
     */
    public function getGroupsByUser(User $user)
    {
        $group = $this->em->getRepository('ApigilityGroup\DoctrineEntity\Group')->findBy([
            'user' => $user->getId(),
        ]);

        return $group;
    }

    /**
     * 删除一个拼团
     *
     * @param $group_id
     * @return bool
     * @throws \Exception
     */
    public function deleteGroup($group_id)
    {
        $group = $this->getGroup($group_id);

        $this->em->remove($group);
        $this->em->flush();

        return true;
    }
}